<?php


namespace App\Http\Middleware;


use App\Services\UserService;
use App\Utils\Code;
use Closure;
use Illuminate\Http\Request;
use Tymon\JWTAuth\Exceptions\JWTException;
use Tymon\JWTAuth\Http\Middleware\BaseMiddleware;

class Authorization extends BaseMiddleware
{

    /**
     * Handle an incoming request.
     *
     * @param Request $request
     * @param Closure $next
     * @param null $source
     * @return mixed
     */
    public function handle(Request $request, Closure $next, $source = null) {
        $request->attributes->add(['source' => $source]);
        // 用户通讯密钥
        $authorization = null;
        // 使用 try 包裹，以捕捉 token 过期所抛出的 JWTException  异常
        try {
            if ($token = $request->input('authorization')) {
                $request->headers->set('authorization', $token);
            }
            // return $request->headers->get('authorization');
            // 检查此次请求中是否带有 token，如果没有则抛出异常
            try {
                $this->checkForToken($request);
            } catch (\Exception $exception) {
                if ($source) {
                    return Code::failure('Unauthorized', Code::UNAUTHORIZED_ACCESS);
                }
            }
            // 检测用户的登录状态，如果正常则通过
            if (!$this->auth->parseToken()->authenticate() && $source) {
                return Code::failure('你的身份信息已过期', Code::EXPIRED);
            }
        } catch (JWTException $exception) {
            // 此处捕获到了 token 过期所抛出的 JWTException 异常
            try {
                $authorization = $this->auth->refresh();
                // 使用一次性登录以保证此次请求的成功
                \Auth::onceUsingId(
                    ($this->auth->manager()->getPayloadFactory()->buildClaimsCollection()->toPlainArray())['sub']
                );
            } catch (\Exception $exception) {
                if ($source){
                    return Code::failure('你的登录状态已过期，请重新登陆', Code::EXPIRED);
                }
            }
        } catch (\Throwable $exception) {
            return Code::exception($exception);
        }
        // 验证用户访问权限
        try {
            (new UserService())->checkAsk($source, $request->header('x-requested-cookie'));
        } catch (\Exception $exception) {
            return Code::exception($exception);
        }
        // 在响应头中返回新的 token
        if ($authorization){
            return $this->setAuthenticationHeader($next($request), $authorization);
        } else {
            return $next($request);
        }
    }
}
